{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# DiscreteFactorGraph"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "license_cell",
      "metadata": {
        "tags": [
          "remove-cell"
        ]
      },
      "source": [
        "GTSAM Copyright 2010-2022, Georgia Tech Research Corporation,\nAtlanta, Georgia 30332-0415\nAll Rights Reserved\n\nAuthors: Frank Dellaert, et al. (see THANKS for the full author list)\n\nSee LICENSE for the license information"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<a href=\"https://colab.research.google.com/github/borglab/gtsam/blob/develop/gtsam/discrete/doc/DiscreteFactorGraph.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "tags": [
          "remove-cell"
        ]
      },
      "outputs": [],
      "source": [
        "try:\n",
        "    import google.colab\n",
        "    %pip install --quiet gtsam\n",
        "except ImportError:\n",
        "    pass  # Not running on Colab, do nothing"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "A `DiscreteFactorGraph` is a factor graph consisting of `DiscreteFactor`s, such as `DecisionTreeFactor`. It represents a joint probability distribution (or a general function) over a set of discrete variables as a product of factors:\n",
        "$$ P(X_1, ..., X_n) \\propto \\prod_i f_i(\\text{Scope}_i) $$\n",
        "where each $f_i$ is a factor over a subset of the variables (its scope).\n",
        "\n",
        "This is an undirected graphical model (a Markov Random Field), and it is used to perform inference tasks like finding the most likely state (`optimize`) or computing marginals (via elimination)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {},
      "outputs": [],
      "source": [
        "import gtsam\n",
        "import numpy as np\n",
        "import graphviz\n",
        "\n",
        "from gtsam.symbol_shorthand import X, Y, Z"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Creating a DiscreteFactorGraph\n",
        "\n",
        "A `DiscreteFactorGraph` is created by adding `DiscreteFactor`s. We will create a simple graph with three variables and three factors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Manually Constructed DiscreteFactorGraph:\n",
            "\n",
            "size: 3\n",
            "factor 0:  f[ (x0,2), ]\n",
            " Choice(x0) \n",
            " 0 Leaf  0.3\n",
            " 1 Leaf  0.7\n",
            "factor 1:  f[ (x0,2), (y0,2), ]\n",
            " Choice(y0) \n",
            " 0 Choice(x0) \n",
            " 0 0 Leaf  0.5\n",
            " 0 1 Leaf  0.1\n",
            " 1 Choice(x0) \n",
            " 1 0 Leaf  0.2\n",
            " 1 1 Leaf  0.9\n",
            "factor 2:  f[ (y0,2), (z0,2), ]\n",
            " Choice(z0) \n",
            " 0 Choice(y0) \n",
            " 0 0 Leaf  0.8\n",
            " 0 1 Leaf  0.3\n",
            " 1 Choice(y0) \n",
            " 1 0 Leaf  0.1\n",
            " 1 1 Leaf  0.6\n"
          ]
        }
      ],
      "source": [
        "# Define keys for three binary variables\n",
        "KeyX = (X(0), 2)\n",
        "KeyY = (Y(0), 2)\n",
        "KeyZ = (Z(0), 2)\n",
        "\n",
        "# Create an empty Factor Graph\n",
        "dfg = gtsam.DiscreteFactorGraph()\n",
        "\n",
        "# Add a unary factor on X (a prior)\n",
        "dfg.add(KeyX, \"0.3 0.7\")\n",
        "\n",
        "# Add a binary factor on X and Y\n",
        "# Values for (X,Y) = (0,0), (0,1), (1,0), (1,1)\n",
        "dfg.add([KeyX, KeyY], \"0.5 0.2 0.1 0.9\")\n",
        "\n",
        "# Add a binary factor on Y and Z\n",
        "# Values for (Y,Z) = (0,0), (0,1), (1,0), (1,1)\n",
        "dfg.add([KeyY, KeyZ], \"0.8 0.1 0.3 0.6\")\n",
        "\n",
        "print(\"Manually Constructed DiscreteFactorGraph:\")\n",
        "dfg.print()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "image/svg+xml": [
              "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
              "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
              " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
              "<!-- Generated by graphviz version 12.0.0 (0)\n",
              " -->\n",
              "<!-- Pages: 1 -->\n",
              "<svg width=\"206pt\" height=\"84pt\"\n",
              " viewBox=\"0.00 0.00 206.00 83.60\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
              "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 79.6)\">\n",
              "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-79.6 202,-79.6 202,4 -4,4\"/>\n",
              "<!-- var8646911284551352320 -->\n",
              "<g id=\"node1\" class=\"node\">\n",
              "<title>var8646911284551352320</title>\n",
              "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-57.6\" rx=\"27\" ry=\"18\"/>\n",
              "<text text-anchor=\"middle\" x=\"27\" y=\"-52.55\" font-family=\"Times,serif\" font-size=\"14.00\">x0</text>\n",
              "</g>\n",
              "<!-- factor0 -->\n",
              "<g id=\"node4\" class=\"node\">\n",
              "<title>factor0</title>\n",
              "<ellipse fill=\"black\" stroke=\"black\" cx=\"27\" cy=\"-1.8\" rx=\"1.8\" ry=\"1.8\"/>\n",
              "</g>\n",
              "<!-- var8646911284551352320&#45;&#45;factor0 -->\n",
              "<g id=\"edge1\" class=\"edge\">\n",
              "<title>var8646911284551352320&#45;&#45;factor0</title>\n",
              "<path fill=\"none\" stroke=\"black\" d=\"M27,-39.28C27,-25.77 27,-8.54 27,-3.96\"/>\n",
              "</g>\n",
              "<!-- factor1 -->\n",
              "<g id=\"node5\" class=\"node\">\n",
              "<title>factor1</title>\n",
              "<ellipse fill=\"black\" stroke=\"black\" cx=\"81\" cy=\"-1.8\" rx=\"1.8\" ry=\"1.8\"/>\n",
              "</g>\n",
              "<!-- var8646911284551352320&#45;&#45;factor1 -->\n",
              "<g id=\"edge2\" class=\"edge\">\n",
              "<title>var8646911284551352320&#45;&#45;factor1</title>\n",
              "<path fill=\"none\" stroke=\"black\" d=\"M41.47,-42.18C55.47,-28.24 75.23,-8.54 79.96,-3.84\"/>\n",
              "</g>\n",
              "<!-- var8718968878589280256 -->\n",
              "<g id=\"node2\" class=\"node\">\n",
              "<title>var8718968878589280256</title>\n",
              "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-57.6\" rx=\"27\" ry=\"18\"/>\n",
              "<text text-anchor=\"middle\" x=\"99\" y=\"-52.55\" font-family=\"Times,serif\" font-size=\"14.00\">y0</text>\n",
              "</g>\n",
              "<!-- var8718968878589280256&#45;&#45;factor1 -->\n",
              "<g id=\"edge3\" class=\"edge\">\n",
              "<title>var8718968878589280256&#45;&#45;factor1</title>\n",
              "<path fill=\"none\" stroke=\"black\" d=\"M93.3,-39.58C88.77,-26.03 82.94,-8.61 81.39,-3.97\"/>\n",
              "</g>\n",
              "<!-- factor2 -->\n",
              "<g id=\"node6\" class=\"node\">\n",
              "<title>factor2</title>\n",
              "<ellipse fill=\"black\" stroke=\"black\" cx=\"117\" cy=\"-1.8\" rx=\"1.8\" ry=\"1.8\"/>\n",
              "</g>\n",
              "<!-- var8718968878589280256&#45;&#45;factor2 -->\n",
              "<g id=\"edge4\" class=\"edge\">\n",
              "<title>var8718968878589280256&#45;&#45;factor2</title>\n",
              "<path fill=\"none\" stroke=\"black\" d=\"M104.7,-39.58C109.23,-26.03 115.06,-8.61 116.61,-3.97\"/>\n",
              "</g>\n",
              "<!-- var8791026472627208192 -->\n",
              "<g id=\"node3\" class=\"node\">\n",
              "<title>var8791026472627208192</title>\n",
              "<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-57.6\" rx=\"27\" ry=\"18\"/>\n",
              "<text text-anchor=\"middle\" x=\"171\" y=\"-52.55\" font-family=\"Times,serif\" font-size=\"14.00\">z0</text>\n",
              "</g>\n",
              "<!-- var8791026472627208192&#45;&#45;factor2 -->\n",
              "<g id=\"edge5\" class=\"edge\">\n",
              "<title>var8791026472627208192&#45;&#45;factor2</title>\n",
              "<path fill=\"none\" stroke=\"black\" d=\"M156.53,-42.18C142.53,-28.24 122.77,-8.54 118.04,-3.84\"/>\n",
              "</g>\n",
              "</g>\n",
              "</svg>\n"
            ],
            "text/plain": [
              "<graphviz.sources.Source at 0x10d0fb530>"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Visualize the Factor Graph structure\n",
        "# Circles are variables, squares are factors.\n",
        "graphviz.Source(dfg.dot())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "182e48bb",
      "metadata": {},
      "source": [
        "### Rich Display in Jupyter\n",
        "A factor graph can be displayed as a list of its component factor tables."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "165643f3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div><p><tt>DiscreteFactorGraph</tt> of size 3</p><p>factor 0:</p><div>\n",
              "<table class='DecisionTreeFactor'>\n",
              "  <thead>\n",
              "    <tr><th>x0</th><th>value</th></tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr><th>0</th><td>0.3</td></tr>\n",
              "    <tr><th>1</th><td>0.7</td></tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "<p>factor 1:</p><div>\n",
              "<table class='DecisionTreeFactor'>\n",
              "  <thead>\n",
              "    <tr><th>x0</th><th>y0</th><th>value</th></tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr><th>0</th><th>0</th><td>0.5</td></tr>\n",
              "    <tr><th>0</th><th>1</th><td>0.2</td></tr>\n",
              "    <tr><th>1</th><th>0</th><td>0.1</td></tr>\n",
              "    <tr><th>1</th><th>1</th><td>0.9</td></tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "<p>factor 2:</p><div>\n",
              "<table class='DecisionTreeFactor'>\n",
              "  <thead>\n",
              "    <tr><th>y0</th><th>z0</th><th>value</th></tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr><th>0</th><th>0</th><td>0.8</td></tr>\n",
              "    <tr><th>0</th><th>1</th><td>0.1</td></tr>\n",
              "    <tr><th>1</th><th>0</th><td>0.3</td></tr>\n",
              "    <tr><th>1</th><th>1</th><td>0.6</td></tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n"
            ],
            "text/markdown": [
              "`DiscreteFactorGraph` of size 3\n",
              "\n",
              "factor 0:\n",
              "|x0|value|\n",
              "|:-:|:-:|\n",
              "|0|0.3|\n",
              "|1|0.7|\n",
              "\n",
              "factor 1:\n",
              "|x0|y0|value|\n",
              "|:-:|:-:|:-:|\n",
              "|0|0|0.5|\n",
              "|0|1|0.2|\n",
              "|1|0|0.1|\n",
              "|1|1|0.9|\n",
              "\n",
              "factor 2:\n",
              "|y0|z0|value|\n",
              "|:-:|:-:|:-:|\n",
              "|0|0|0.8|\n",
              "|0|1|0.1|\n",
              "|1|0|0.3|\n",
              "|1|1|0.6|\n",
              "\n"
            ],
            "text/plain": [
              "\n",
              "size: 3\n",
              "factor 0:  f[ (x0,2), ]\n",
              " Choice(x0) \n",
              " 0 Leaf  0.3\n",
              " 1 Leaf  0.7\n",
              "factor 1:  f[ (x0,2), (y0,2), ]\n",
              " Choice(y0) \n",
              " 0 Choice(x0) \n",
              " 0 0 Leaf  0.5\n",
              " 0 1 Leaf  0.1\n",
              " 1 Choice(x0) \n",
              " 1 0 Leaf  0.2\n",
              " 1 1 Leaf  0.9\n",
              "factor 2:  f[ (y0,2), (z0,2), ]\n",
              " Choice(z0) \n",
              " 0 Choice(y0) \n",
              " 0 0 Leaf  0.8\n",
              " 0 1 Leaf  0.3\n",
              " 1 Choice(y0) \n",
              " 1 0 Leaf  0.1\n",
              " 1 1 Leaf  0.6"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "dfg"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Inference on a DiscreteFactorGraph"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Unnormalized probability at (X=1, Y=1, Z=0): 0.1890\n",
            "\n",
            "Most Probable Explanation (MPE) Solution:\n",
            "DiscreteValues{8646911284551352320: 1, 8718968878589280256: 1, 8791026472627208192: 1}\n"
          ]
        }
      ],
      "source": [
        "# --- Evaluation ---\n",
        "# Calculate the product of all factor values for a given assignment.\n",
        "values = gtsam.DiscreteValues()\n",
        "values[X(0)] = 1\n",
        "values[Y(0)] = 1\n",
        "values[Z(0)] = 0\n",
        "\n",
        "# P(X=1,Y=1,Z=0) ∝ f1(1) * f2(1,1) * f3(1,0)\n",
        "#                  = 0.7  *   0.9   *   0.3 = 0.189\n",
        "prob = dfg(values)\n",
        "print(f\"Unnormalized probability at (X=1, Y=1, Z=0): {prob:.4f}\")\n",
        "\n",
        "# --- Optimization (MPE) ---\n",
        "# Find the assignment with the highest product of probabilities.\n",
        "# This is done using the max-product algorithm (belief propagation).\n",
        "mpe_solution = dfg.optimize()\n",
        "print(\"\\nMost Probable Explanation (MPE) Solution:\")\n",
        "print(mpe_solution)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "--- Resulting Bayes Net after elimination ---\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<div><p><tt>DiscreteBayesNet</tt> of size 3</p><div>\n",
              "<p>  <i>P(x0|y0):</i></p>\n",
              "<table class='DiscreteConditional'>\n",
              "  <thead>\n",
              "    <tr><th><i>y0</i></th><th>0</th><th>1</th></tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr><th>0</th><td>0.681818</td><td>0.318182</td></tr>\n",
              "    <tr><th>1</th><td>0.0869565</td><td>0.913043</td></tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "<div>\n",
              "<p>  <i>P(z0|y0):</i></p>\n",
              "<table class='DiscreteConditional'>\n",
              "  <thead>\n",
              "    <tr><th><i>y0</i></th><th>0</th><th>1</th></tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr><th>0</th><td>0.888889</td><td>0.111111</td></tr>\n",
              "    <tr><th>1</th><td>0.333333</td><td>0.666667</td></tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "<div>\n",
              "<p>  <i>P(y0):</i></p>\n",
              "<div>\n",
              "<table class='DecisionTreeFactor'>\n",
              "  <thead>\n",
              "    <tr><th>y0</th><th>value</th></tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr><th>0</th><td>0.241758</td></tr>\n",
              "    <tr><th>1</th><td>0.758242</td></tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n"
            ],
            "text/markdown": [
              "`DiscreteBayesNet` of size 3\n",
              "\n",
              " *P(x0|y0):*\n",
              "\n",
              "|*y0*|0|1|\n",
              "|:-:|:-:|:-:|\n",
              "|0|0.681818|0.318182|\n",
              "|1|0.0869565|0.913043|\n",
              "\n",
              " *P(z0|y0):*\n",
              "\n",
              "|*y0*|0|1|\n",
              "|:-:|:-:|:-:|\n",
              "|0|0.888889|0.111111|\n",
              "|1|0.333333|0.666667|\n",
              "\n",
              " *P(y0):*\n",
              "\n",
              "|y0|value|\n",
              "|:-:|:-:|\n",
              "|0|0.241758|\n",
              "|1|0.758242|\n",
              "\n"
            ],
            "text/plain": [
              "DiscreteBayesNet\n",
              " \n",
              "size: 3\n",
              "conditional 0:  P( x0 | y0 ):\n",
              " Choice(y0) \n",
              " 0 Choice(x0) \n",
              " 0 0 Leaf 0.68181818\n",
              " 0 1 Leaf 0.31818182\n",
              " 1 Choice(x0) \n",
              " 1 0 Leaf 0.086956522\n",
              " 1 1 Leaf 0.91304348\n",
              "\n",
              "conditional 1:  P( z0 | y0 ):\n",
              " Choice(z0) \n",
              " 0 Choice(y0) \n",
              " 0 0 Leaf 0.88888889\n",
              " 0 1 Leaf 0.33333333\n",
              " 1 Choice(y0) \n",
              " 1 0 Leaf 0.11111111\n",
              " 1 1 Leaf 0.66666667\n",
              "\n",
              "conditional 2:  P( y0 ):\n",
              " Choice(y0) \n",
              " 0 Leaf 0.24175824\n",
              " 1 Leaf 0.75824176\n"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# --- Elimination (Sum-Product) ---\n",
        "# Eliminate variables from the graph to obtain a Bayes Net (or just a marginal).\n",
        "# This computes the marginal probability distribution.\n",
        "ordering = gtsam.Ordering()\n",
        "ordering.push_back(Z(0))\n",
        "ordering.push_back(X(0))\n",
        "ordering.push_back(Y(0))\n",
        "\n",
        "# Eliminating the graph produces a Bayes Net P(X,Y,Z) = P(Z|Y)P(Y|X)P(X)\n",
        "bayes_net = dfg.eliminateSequential(ordering)\n",
        "print(\"--- Resulting Bayes Net after elimination ---\")\n",
        "bayes_net"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "dbe26b13",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "image/svg+xml": [
              "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
              "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
              " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
              "<!-- Generated by graphviz version 12.0.0 (0)\n",
              " -->\n",
              "<!-- Pages: 1 -->\n",
              "<svg width=\"134pt\" height=\"116pt\"\n",
              " viewBox=\"0.00 0.00 134.00 116.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
              "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n",
              "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-112 130,-112 130,4 -4,4\"/>\n",
              "<!-- var8646911284551352320 -->\n",
              "<g id=\"node1\" class=\"node\">\n",
              "<title>var8646911284551352320</title>\n",
              "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
              "<text text-anchor=\"middle\" x=\"27\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">x0</text>\n",
              "</g>\n",
              "<!-- var8718968878589280256 -->\n",
              "<g id=\"node2\" class=\"node\">\n",
              "<title>var8718968878589280256</title>\n",
              "<ellipse fill=\"none\" stroke=\"black\" cx=\"63\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
              "<text text-anchor=\"middle\" x=\"63\" y=\"-84.95\" font-family=\"Times,serif\" font-size=\"14.00\">y0</text>\n",
              "</g>\n",
              "<!-- var8718968878589280256&#45;&gt;var8646911284551352320 -->\n",
              "<g id=\"edge2\" class=\"edge\">\n",
              "<title>var8718968878589280256&#45;&gt;var8646911284551352320</title>\n",
              "<path fill=\"none\" stroke=\"black\" d=\"M54.65,-72.76C50.42,-64.55 45.19,-54.37 40.42,-45.09\"/>\n",
              "<polygon fill=\"black\" stroke=\"black\" points=\"43.68,-43.79 36,-36.49 37.46,-46.99 43.68,-43.79\"/>\n",
              "</g>\n",
              "<!-- var8791026472627208192 -->\n",
              "<g id=\"node3\" class=\"node\">\n",
              "<title>var8791026472627208192</title>\n",
              "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
              "<text text-anchor=\"middle\" x=\"99\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">z0</text>\n",
              "</g>\n",
              "<!-- var8718968878589280256&#45;&gt;var8791026472627208192 -->\n",
              "<g id=\"edge1\" class=\"edge\">\n",
              "<title>var8718968878589280256&#45;&gt;var8791026472627208192</title>\n",
              "<path fill=\"none\" stroke=\"black\" d=\"M71.35,-72.76C75.58,-64.55 80.81,-54.37 85.58,-45.09\"/>\n",
              "<polygon fill=\"black\" stroke=\"black\" points=\"88.54,-46.99 90,-36.49 82.32,-43.79 88.54,-46.99\"/>\n",
              "</g>\n",
              "</g>\n",
              "</svg>\n"
            ],
            "text/plain": [
              "<graphviz.sources.Source at 0x10d251c40>"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Visualize the Bayes net structure using graphviz\n",
        "graphviz.Source(bayes_net.dot())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "609a186c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "--- Resulting Bayes Tree after elimination ---\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<div><p><tt>DiscreteBayesTree</tt> of size 3</p><div>\n",
              "<p>  <i>P(x0,y0):</i></p>\n",
              "<div>\n",
              "<table class='DecisionTreeFactor'>\n",
              "  <thead>\n",
              "    <tr><th>x0</th><th>y0</th><th>value</th></tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr><th>0</th><th>0</th><td>0.164835</td></tr>\n",
              "    <tr><th>0</th><th>1</th><td>0.0659341</td></tr>\n",
              "    <tr><th>1</th><th>0</th><td>0.0769231</td></tr>\n",
              "    <tr><th>1</th><th>1</th><td>0.692308</td></tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div><div>\n",
              "<p>  <i>P(z0|y0):</i></p>\n",
              "<table class='DiscreteConditional'>\n",
              "  <thead>\n",
              "    <tr><th><i>y0</i></th><th>0</th><th>1</th></tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr><th>0</th><td>0.888889</td><td>0.111111</td></tr>\n",
              "    <tr><th>1</th><td>0.333333</td><td>0.666667</td></tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/markdown": [
              "`DiscreteBayesTree` of size 3\n",
              "\n",
              "\n",
              " *P(x0,y0):*\n",
              "\n",
              "|x0|y0|value|\n",
              "|:-:|:-:|:-:|\n",
              "|0|0|0.164835|\n",
              "|0|1|0.0659341|\n",
              "|1|0|0.0769231|\n",
              "|1|1|0.692308|\n",
              "\n",
              " *P(z0|y0):*\n",
              "\n",
              "|*y0*|0|1|\n",
              "|:-:|:-:|:-:|\n",
              "|0|0.888889|0.111111|\n",
              "|1|0.333333|0.666667|\n"
            ],
            "text/plain": [
              "DiscreteBayesTree\n",
              ": cliques: 2, variables: 3\n",
              "DiscreteBayesTree\n",
              "- P( x0 y0 ):\n",
              " Choice(y0) \n",
              " 0 Choice(x0) \n",
              " 0 0 Leaf 0.16483516\n",
              " 0 1 Leaf 0.076923077\n",
              " 1 Choice(x0) \n",
              " 1 0 Leaf 0.065934066\n",
              " 1 1 Leaf 0.69230769\n",
              "\n",
              "DiscreteBayesTree\n",
              "| - P( z0 | y0 ):\n",
              " Choice(z0) \n",
              " 0 Choice(y0) \n",
              " 0 0 Leaf 0.88888889\n",
              " 0 1 Leaf 0.33333333\n",
              " 1 Choice(y0) \n",
              " 1 0 Leaf 0.11111111\n",
              " 1 1 Leaf 0.66666667\n"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# --- Elimination into a Bayes tree (Sum-Product) ---\n",
        "# We can also produce a Bayes tree, which is typically more efficient to do.\n",
        "bayes_tree = dfg.eliminateMultifrontal(ordering)\n",
        "print(\"--- Resulting Bayes Tree after elimination ---\")\n",
        "bayes_tree"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "4d2755da",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "image/svg+xml": [
              "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
              "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
              " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
              "<!-- Generated by graphviz version 12.0.0 (0)\n",
              " -->\n",
              "<!-- Title: G Pages: 1 -->\n",
              "<svg width=\"81pt\" height=\"116pt\"\n",
              " viewBox=\"0.00 0.00 81.02 116.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
              "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n",
              "<title>G</title>\n",
              "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-112 77.02,-112 77.02,4 -4,4\"/>\n",
              "<!-- 0 -->\n",
              "<g id=\"node1\" class=\"node\">\n",
              "<title>0</title>\n",
              "<ellipse fill=\"none\" stroke=\"black\" cx=\"36.51\" cy=\"-90\" rx=\"34.46\" ry=\"18\"/>\n",
              "<text text-anchor=\"middle\" x=\"36.51\" y=\"-84.95\" font-family=\"Times,serif\" font-size=\"14.00\">x0, y0</text>\n",
              "</g>\n",
              "<!-- 1 -->\n",
              "<g id=\"node2\" class=\"node\">\n",
              "<title>1</title>\n",
              "<ellipse fill=\"none\" stroke=\"black\" cx=\"36.51\" cy=\"-18\" rx=\"36.51\" ry=\"18\"/>\n",
              "<text text-anchor=\"middle\" x=\"36.51\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">z0 : y0</text>\n",
              "</g>\n",
              "<!-- 0&#45;&gt;1 -->\n",
              "<g id=\"edge1\" class=\"edge\">\n",
              "<title>0&#45;&gt;1</title>\n",
              "<path fill=\"none\" stroke=\"black\" d=\"M36.51,-71.7C36.51,-64.41 36.51,-55.73 36.51,-47.54\"/>\n",
              "<polygon fill=\"black\" stroke=\"black\" points=\"40.01,-47.62 36.51,-37.62 33.01,-47.62 40.01,-47.62\"/>\n",
              "</g>\n",
              "</g>\n",
              "</svg>\n"
            ],
            "text/plain": [
              "<graphviz.sources.Source at 0x10a87eea0>"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Visualize the Bayes tree structure using graphviz\n",
        "graphviz.Source(bayes_tree.dot())"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "py312",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}